//! MOV 指令编码模块
//! 
//! 实现 8086 MOV 指令的各种变体编码

use crate::ast::{MemoryOperand, Operand};
use crate::error::{AssemblerError, Result};
use super::memory::MemoryEncoder;
use super::registers::RegisterEncoding;

/// MOV 指令编码器
pub struct MovEncoder;

impl MovEncoder {
    /// 编码 MOV 指令
    pub fn encode(&self, operands: &[Operand]) -> Result<Vec<u8>> {
        if operands.len() != 2 {
            return Err(AssemblerError::OperandError {
                message: "移动 指令需要 2 个操作数".to_string(),
                line: 0,
            });
        }

        let dst = &operands[0];
        let src = &operands[1];

        match (dst, src) {
            // MOV reg, reg
            (Operand::Register(dst_reg), Operand::Register(src_reg)) => {
                // 检查是否是段寄存器操作
                if RegisterEncoding::is_segment_register(dst_reg) {
                    // MOV seg_reg, reg (8C /r)
                    self.encode_mov_seg_reg(dst_reg, src_reg)
                } else if RegisterEncoding::is_segment_register(src_reg) {
                    // MOV reg, seg_reg (8E /r)
                    self.encode_mov_reg_seg(dst_reg, src_reg)
                } else {
                    // MOV reg, reg (普通寄存器)
                    self.encode_mov_reg_reg(dst_reg, src_reg)
                }
            }
            // MOV reg, imm
            (Operand::Register(reg), Operand::Immediate(imm)) => {
                // 段寄存器不能直接加载立即数，需要通过通用寄存器
                if RegisterEncoding::is_segment_register(reg) {
                    return Err(AssemblerError::OperandError {
                        message: format!("段寄存器 {} 不能直接加载立即数，请先加载到通用寄存器", reg),
                        line: 0,
                    });
                }
                self.encode_mov_reg_imm(reg, *imm)
            }
            // MOV reg, mem
            (Operand::Register(reg), Operand::Memory(mem)) => {
                if RegisterEncoding::is_segment_register(reg) {
                    // MOV seg_reg, mem (8C /r)
                    self.encode_mov_seg_mem(reg, mem)
                } else {
                    // MOV reg, mem (普通寄存器)
                    self.encode_mov_reg_mem(reg, mem)
                }
            }
            // MOV mem, reg
            (Operand::Memory(mem), Operand::Register(reg)) => {
                if RegisterEncoding::is_segment_register(reg) {
                    // MOV mem, seg_reg (8E /r)
                    self.encode_mov_mem_seg(mem, reg)
                } else {
                    // MOV mem, reg (普通寄存器)
                    self.encode_mov_mem_reg(mem, reg)
                }
            }
            _ => Err(AssemblerError::OperandError {
                message: format!("不支持的移动操作数组合: {:?}", (dst, src)),
                line: 0,
            }),
        }
    }

    /// MOV reg, reg
    /// 编码: 1000100w | mod reg r/m
    fn encode_mov_reg_reg(&self, dst: &str, src: &str) -> Result<Vec<u8>> {
        let dst_code = RegisterEncoding::get_16bit_register_code(dst)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", dst),
                line: 0,
            })?;
        let src_code = RegisterEncoding::get_16bit_register_code(src)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", src),
                line: 0,
            })?;

        // 1000100w = 0x88 (8位) 或 0x89 (16位)
        // w=1 表示16位操作，mod=11 表示寄存器模式
        let opcode = 0x89; // 16位寄存器到寄存器
        let modrm = (0b11 << 6) | (dst_code << 3) | src_code;

        Ok(vec![opcode, modrm])
    }

    /// MOV reg, imm
    /// 编码: 1011wrrr | imm (低字节) | imm (高字节，如果w=1)
    fn encode_mov_reg_imm(&self, reg: &str, imm: i64) -> Result<Vec<u8>> {
        let reg_code = RegisterEncoding::get_16bit_register_code(reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", reg),
                line: 0,
            })?;

        // 检查立即数范围（16位有符号：-32768 到 32767）
        if imm < -32768 || imm > 65535 {
            return Err(AssemblerError::OperandError {
                message: format!("立即数超出16位范围: {}", imm),
                line: 0,
            });
        }

        // 1011wrrr = 0xB8 + reg_code (w=1表示16位)
        let opcode = 0xB8 + reg_code;
        let imm_bytes = if imm >= -128 && imm <= 127 {
            // 8位立即数（使用8位MOV）
            vec![0xB0 + reg_code, imm as u8]
        } else {
            // 16位立即数
            let imm_u16 = imm as u16;
            vec![opcode, imm_u16 as u8, (imm_u16 >> 8) as u8]
        };

        Ok(imm_bytes)
    }

    /// MOV reg, mem
    /// 编码: 1000101w | mod reg r/m | [disp]
    fn encode_mov_reg_mem(&self, reg: &str, mem: &MemoryOperand) -> Result<Vec<u8>> {
        let reg_code = RegisterEncoding::get_16bit_register_code(reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", reg),
                line: 0,
            })?;

        // 1000101w = 0x8B (16位)
        let opcode = 0x8B;
        let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, reg_code)?;

        let mut result = vec![opcode, modrm];
        result.extend_from_slice(&disp_bytes);
        Ok(result)
    }

    /// MOV mem, reg
    fn encode_mov_mem_reg(&self, mem: &MemoryOperand, reg: &str) -> Result<Vec<u8>> {
        let reg_code = RegisterEncoding::get_16bit_register_code(reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", reg),
                line: 0,
            })?;

        // 1000100w = 0x89 (16位)
        let opcode = 0x89;
        let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, reg_code)?;

        let mut result = vec![opcode, modrm];
        result.extend_from_slice(&disp_bytes);
        Ok(result)
    }

    /// MOV seg_reg, reg
    /// 编码: 10001100 | mod seg_reg r/m
    /// 操作码: 0x8C
    fn encode_mov_seg_reg(&self, seg_reg: &str, reg: &str) -> Result<Vec<u8>> {
        let seg_code = RegisterEncoding::get_segment_register_code(seg_reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的段寄存器: {}", seg_reg),
                line: 0,
            })?;
        
        let reg_code = RegisterEncoding::get_16bit_register_code(reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", reg),
                line: 0,
            })?;

        // 0x8C = 10001100
        // mod = 11 (寄存器模式), reg = seg_code, r/m = reg_code
        let opcode = 0x8C;
        let modrm = (0b11 << 6) | (seg_code << 3) | reg_code;

        Ok(vec![opcode, modrm])
    }

    /// MOV reg, seg_reg
    /// 编码: 10001110 | mod reg seg_reg
    /// 操作码: 0x8E
    fn encode_mov_reg_seg(&self, reg: &str, seg_reg: &str) -> Result<Vec<u8>> {
        let reg_code = RegisterEncoding::get_16bit_register_code(reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的16位寄存器: {}", reg),
                line: 0,
            })?;
        
        let seg_code = RegisterEncoding::get_segment_register_code(seg_reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的段寄存器: {}", seg_reg),
                line: 0,
            })?;

        // 0x8E = 10001110
        // mod = 11 (寄存器模式), reg = reg_code, r/m = seg_code
        let opcode = 0x8E;
        let modrm = (0b11 << 6) | (reg_code << 3) | seg_code;

        Ok(vec![opcode, modrm])
    }

    /// MOV seg_reg, mem
    /// 编码: 10001100 | mod seg_reg r/m | [disp]
    /// 操作码: 0x8C
    fn encode_mov_seg_mem(&self, seg_reg: &str, mem: &MemoryOperand) -> Result<Vec<u8>> {
        let seg_code = RegisterEncoding::get_segment_register_code(seg_reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的段寄存器: {}", seg_reg),
                line: 0,
            })?;

        // 0x8C = 10001100
        let opcode = 0x8C;
        let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, seg_code)?;

        let mut result = vec![opcode, modrm];
        result.extend_from_slice(&disp_bytes);
        Ok(result)
    }

    /// MOV mem, seg_reg
    /// 编码: 10001110 | mod reg r/m | [disp]
    /// 操作码: 0x8E
    fn encode_mov_mem_seg(&self, mem: &MemoryOperand, seg_reg: &str) -> Result<Vec<u8>> {
        let seg_code = RegisterEncoding::get_segment_register_code(seg_reg)
            .ok_or_else(|| AssemblerError::OperandError {
                message: format!("无效的段寄存器: {}", seg_reg),
                line: 0,
            })?;

        // 0x8E = 10001110
        // 注意：这里 seg_code 放在 r/m 字段
        let opcode = 0x8E;
        let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, seg_code)?;

        let mut result = vec![opcode, modrm];
        result.extend_from_slice(&disp_bytes);
        Ok(result)
    }

    /// 编码交换指令（XCHG）
    /// 
    /// 支持的操作数组合：
    /// - XCHG reg, reg
    /// - XCHG reg, mem
    /// - XCHG mem, reg
    /// 
    /// 特殊编码：
    /// - XCHG AX, reg 或 XCHG reg, AX: 单字节编码 (0x90 + reg)
    pub fn encode_xchg(&self, operands: &[Operand]) -> Result<Vec<u8>> {
        if operands.len() != 2 {
            return Err(AssemblerError::OperandError {
                message: "交换 指令需要 2 个操作数".to_string(),
                line: 0,
            });
        }

        let op1 = &operands[0];
        let op2 = &operands[1];

        match (op1, op2) {
            // XCHG reg, reg
            (Operand::Register(reg1), Operand::Register(reg2)) => {
                // 检查是否是段寄存器（XCHG不支持段寄存器）
                if RegisterEncoding::is_segment_register(reg1) || 
                   RegisterEncoding::is_segment_register(reg2) {
                    return Err(AssemblerError::OperandError {
                        message: "交换 指令不支持段寄存器".to_string(),
                        line: 0,
                    });
                }

                let reg1_code = RegisterEncoding::get_16bit_register_code(reg1)
                    .ok_or_else(|| AssemblerError::OperandError {
                        message: format!("无效的16位寄存器: {}", reg1),
                        line: 0,
                    })?;
                let reg2_code = RegisterEncoding::get_16bit_register_code(reg2)
                    .ok_or_else(|| AssemblerError::OperandError {
                        message: format!("无效的16位寄存器: {}", reg2),
                        line: 0,
                    })?;

                // 特殊编码：XCHG AX, reg 或 XCHG reg, AX (单字节)
                if reg1_code == 0 && reg2_code != 0 {
                    // XCHG AX, reg2
                    Ok(vec![0x90 + reg2_code])
                } else if reg1_code != 0 && reg2_code == 0 {
                    // XCHG reg1, AX
                    Ok(vec![0x90 + reg1_code])
                } else {
                    // XCHG reg, reg (通用编码)
                    // 1000011w = 0x87 (16位)
                    let opcode = 0x87;
                    let modrm = (0b11 << 6) | (reg1_code << 3) | reg2_code;
                    Ok(vec![opcode, modrm])
                }
            }
            // XCHG reg, mem
            (Operand::Register(reg), Operand::Memory(mem)) => {
                if RegisterEncoding::is_segment_register(reg) {
                    return Err(AssemblerError::OperandError {
                        message: "交换 指令不支持段寄存器".to_string(),
                        line: 0,
                    });
                }

                let reg_code = RegisterEncoding::get_16bit_register_code(reg)
                    .ok_or_else(|| AssemblerError::OperandError {
                        message: format!("无效的16位寄存器: {}", reg),
                        line: 0,
                    })?;

                // 1000011w = 0x87 (16位)
                let opcode = 0x87;
                let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, reg_code)?;

                let mut result = vec![opcode, modrm];
                result.extend_from_slice(&disp_bytes);
                Ok(result)
            }
            // XCHG mem, reg
            (Operand::Memory(mem), Operand::Register(reg)) => {
                if RegisterEncoding::is_segment_register(reg) {
                    return Err(AssemblerError::OperandError {
                        message: "交换 指令不支持段寄存器".to_string(),
                        line: 0,
                    });
                }

                let reg_code = RegisterEncoding::get_16bit_register_code(reg)
                    .ok_or_else(|| AssemblerError::OperandError {
                        message: format!("无效的16位寄存器: {}", reg),
                        line: 0,
                    })?;

                // 1000011w = 0x87 (16位)
                // 注意：XCHG mem, reg 和 XCHG reg, mem 编码相同（交换操作）
                let opcode = 0x87;
                let (modrm, disp_bytes) = MemoryEncoder::encode_memory_operand(mem, reg_code)?;

                let mut result = vec![opcode, modrm];
                result.extend_from_slice(&disp_bytes);
                Ok(result)
            }
            _ => Err(AssemblerError::OperandError {
                message: "交换 指令不支持立即数操作数".to_string(),
                line: 0,
            }),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ast::Operand;

    #[test]
    fn test_encode_mov_reg_reg() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Register("基址".to_string()),
        ];
        let result = encoder.encode(&operands).unwrap();
        // MOV AX, BX = 89 C3 (dst=AX=0, src=BX=3, modrm=0b11000011=0xC3)
        assert_eq!(result, vec![0x89, 0xC3]);
    }

    #[test]
    fn test_encode_mov_reg_imm() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Immediate(10),
        ];
        let result = encoder.encode(&operands).unwrap();
        // MOV AX, 10 (8位立即数) = B0 0A
        assert_eq!(result, vec![0xB0, 0x0A]);
    }

    #[test]
    fn test_encode_mov_reg_imm_large() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Immediate(0x1234),
        ];
        let result = encoder.encode(&operands).unwrap();
        // MOV AX, 0x1234 = B8 34 12
        assert_eq!(result, vec![0xB8, 0x34, 0x12]);
    }

    #[test]
    fn test_encode_mov_seg_reg() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("数据段".to_string()),
            Operand::Register("累加器".to_string()),
        ];
        let result = encoder.encode(&operands).unwrap();
        // MOV DS, AX = 8C D8
        assert_eq!(result, vec![0x8C, 0xD8]);
    }

    #[test]
    fn test_encode_mov_reg_seg() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Register("数据段".to_string()),
        ];
        let result = encoder.encode(&operands).unwrap();
        // MOV AX, DS = 8E C3 (reg=AX=0, seg=DS=3, modrm=0b11000011=0xC3)
        assert_eq!(result, vec![0x8E, 0xC3]);
    }

    #[test]
    fn test_encode_mov_invalid_operand_count() {
        let encoder = MovEncoder;
        let operands = vec![Operand::Register("累加器".to_string())];
        let result = encoder.encode(&operands);
        assert!(result.is_err());
    }

    #[test]
    fn test_encode_mov_seg_reg_imm_error() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("数据段".to_string()),
            Operand::Immediate(10),
        ];
        let result = encoder.encode(&operands);
        assert!(result.is_err());
    }

    #[test]
    fn test_encode_xchg_ax_reg() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Register("基址".to_string()),
        ];
        let result = encoder.encode_xchg(&operands).unwrap();
        // XCHG AX, BX = 90 + 3 = 0x93
        assert_eq!(result, vec![0x93]);
    }

    #[test]
    fn test_encode_xchg_reg_ax() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("基址".to_string()),
            Operand::Register("累加器".to_string()),
        ];
        let result = encoder.encode_xchg(&operands).unwrap();
        // XCHG BX, AX = 90 + 3 = 0x93
        assert_eq!(result, vec![0x93]);
    }

    #[test]
    fn test_encode_xchg_reg_reg() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("基址".to_string()),
            Operand::Register("计数".to_string()),
        ];
        let result = encoder.encode_xchg(&operands).unwrap();
        // XCHG BX, CX = 87 D9 (reg1=BX=3, reg2=CX=1, modrm=0b11011001=0xD9)
        assert_eq!(result, vec![0x87, 0xD9]);
    }

    #[test]
    fn test_encode_xchg_reg_mem() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Memory(MemoryOperand {
                base: Some("基址".to_string()),
                index: None,
                scale: None,
                displacement: None,
            }),
        ];
        let result = encoder.encode_xchg(&operands).unwrap();
        // XCHG AX, [BX] = 87 07
        assert_eq!(result, vec![0x87, 0x07]);
    }

    #[test]
    fn test_encode_xchg_invalid_immediate() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("累加器".to_string()),
            Operand::Immediate(10),
        ];
        let result = encoder.encode_xchg(&operands);
        assert!(result.is_err());
    }

    #[test]
    fn test_encode_xchg_invalid_segment() {
        let encoder = MovEncoder;
        let operands = vec![
            Operand::Register("数据段".to_string()),
            Operand::Register("累加器".to_string()),
        ];
        let result = encoder.encode_xchg(&operands);
        assert!(result.is_err());
    }
}

